package com.xhs.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;

/**
 * @desc: CompletableFuture 两个任务组合回调
 * @projectName: java-tools-parent
 * @author: xhs
 * @date: 2025-08-09 周六 16:10
 */
@Slf4j
@RestController
@RequestMapping("/completableFuture1")
public class CompletableFuture1Controller {

    @Resource
    private Executor taskExecutor;

    /**
     * 任务一和任务二执行完成后，再执行任务三，且无返回值
     */
    @GetMapping("/test01")
    public void test01() {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            log.info("任务A线程：" + Thread.currentThread().getName());
            return "hello";
        }, taskExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            log.info("任务B线程：" + Thread.currentThread().getName());
            return "world";
        }, taskExecutor);

        futureA.runAfterBoth(futureB, () -> {
            log.info("执行任务C，任务C线程：" + Thread.currentThread().getName());
        });
    }

    /**
     * 任务一和任务二执行完成后,再执行任务三，接收任务一二的结果作为参数，没有返回值
     */
    @GetMapping("/test02")
    public void test02() {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            log.info("任务A线程：" + Thread.currentThread().getName());
            return "hello";
        }, taskExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            log.info("任务B线程：" + Thread.currentThread().getName());
            return "world";
        }, taskExecutor);

        futureA.thenAcceptBoth(futureB, (AResult, BResult) -> {
            log.info("执行任务C结果" + AResult + " " + BResult + "，任务C线程：" + Thread.currentThread().getName());
        });
    }

    /**
     * 任务一和任务二执行完成后,再执行任务三，接收任务一二的结果作为参数,有返回值
     */
    @GetMapping("/test03")
    public void test03() {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            log.info("任务A线程：" + Thread.currentThread().getName());
            return "hello";
        }, taskExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            log.info("任务B线程：" + Thread.currentThread().getName());
            return "world";
        }, taskExecutor);

        CompletableFuture<String> futureC = futureA.thenCombine(futureB, (AResult, BResult) -> {
            log.info("执行任务C结果" + AResult + " " + BResult + "，任务C线程：" + Thread.currentThread().getName());
            return AResult + " " + BResult;
        });
        log.info("futureC.join():{}", futureC.join());
    }

    /**
     * 两个任务，只要有一个任务完成，就执行任务三， 不接受参数，没有返回值
     */
    @GetMapping("/test04")
    public void test04() throws ExecutionException, InterruptedException {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("任务A线程：" + Thread.currentThread().getName());
            return "hello";
        }, taskExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            log.info("任务B线程：" + Thread.currentThread().getName());
            return "world";
        }, taskExecutor);

        CompletableFuture<Void> futureC = futureA.runAfterEither(futureB, () -> {
            log.info("执行任务C");
        });
        log.info("futureC.join():{}", futureC.join());
    }

    /**
     * 两个任务，只要有一个任务完成，就执行任务三， 接收参数，没有返回值
     */
    @GetMapping("/test05")
    public void test05() {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("任务A线程：" + Thread.currentThread().getName());
            return "hello";
        }, taskExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            log.info("任务B线程：" + Thread.currentThread().getName());
            return "world";
        }, taskExecutor);

        CompletableFuture<Void> futureC = futureA.acceptEither(futureB, (param) -> {
            log.info("执行任务C，参数：" + param);
        });
        log.info("futureC.join():{}", futureC.join());
    }

    /**
     * 两个任务，只要有一个任务完成，就执行任务三， 接收参数，有返回值
     */
    @GetMapping("/test06")
    public void test06() {
        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("任务A线程：" + Thread.currentThread().getName());
            return "hello";
        }, taskExecutor);

        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            log.info("任务B线程：" + Thread.currentThread().getName());
            return "world";
        }, taskExecutor);

        CompletableFuture<String> futureC = futureA.applyToEither(futureB, (param) -> {
            log.info("执行任务C，参数：" + param);
            return param;
        });
        log.info("futureC.join():{}", futureC.join());
    }
}
